package cn.lg.soar.common.util.data;

import com.google.common.base.CaseFormat;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 字符串工具类
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface StringUtil {

    String EMPTY = "";
    String UNDERLINE = "_";
    String MIDDLE_LINE = "-";
    String COLON = ":";
    String COMMA = ",";
    String POINT = ".";
    String GET = "get";
    String SET = "set";
    String SLASH = "/";
    String ASTERISK = "*";
    String DOUBLE_ASTERISK = "**";

    String CHARSET = "UTF-8";

    String MATCHER_SJ = "\\S+";
    String MATCHER_$ = "$";

    String[] EMPTY_ARRAY = {};

    Pattern GET_NUMBER_PATTERN = Pattern.compile("[^0-9]");

    /**
     * 是否是空白字符串
     * @param cs
     * @return
     */
    static boolean isBlank(CharSequence cs) {
        int strLen;
        if(null == cs || (strLen = cs.length()) == 0){
            return true;
        }
        for(int i = 0; i < strLen; ++i) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 字段名转get方法名
     */
    static String fieldToGetMethod(String fieldName) {
        return StringUtil.GET + StringUtil.upperFirstCase(fieldName);
    }

    /**
     * 字段名转set方法名
     */
    static String fieldToSetMethod(String fieldName) {
        return StringUtil.SET + StringUtil.upperFirstCase(fieldName);
    }

    /**
     * 去空格
     * @param str
     * @return
     */
    static String trim(String str) {
        return str == null ? null : str.trim();
    }

    /**
     * 转小写
     * @param str
     */
    static String toLowerCase(String str) {
        if(null == str){
            return null;
        }
        return str.toLowerCase();
    }

    /**
     * 转大写
     * @param str
     */
    static String toUpperCase(String str) {
        if(null == str){
            return null;
        }
        return str.toUpperCase();
    }

    /**
     * 首字母 转小写
     * @param str
     */
    static String lowerFirstCase(String str) {
        if(null == str){
            return null;
        }
        char[] chars = str.toCharArray();
        char first = (char) (chars[0] | ' ');
        if(first != chars[0]){
            chars[0] = first;
            return new String(chars);
        }
        return str;
    }

    /**
     * 首字母 转大写
     * @param str
     */
    static String upperFirstCase(String str) {
        if(null == str){
            return null;
        }
        char[] chars = str.toCharArray();
        char first = (char) (chars[0] & '_');
        if(first != chars[0]){
            chars[0] = first;
            return new String(chars);
        }
        return str;
    }

    /**
     * 下划线转驼峰
     * @param str
     * @return
     */
    static String underscoreToCamel(String str) {
        if (str == null) {
            return null;
        }
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, str);
    }

    /**
     * 驼峰转下划线
     * @param str
     * @return
     */
    static String camelToUnderscore(String str) {
        if (str == null) {
            return null;
        }
        return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, str);
    }

    /**
     * 拆分字符串
     * @param str 字符串
     * @param regex 拆分的字符
     * @param limit
     * @return
     */
    static String[] split(String str, String regex, int limit) {
        if(null == str){
            return null;
        }
        return str.split(regex, limit);
    }

    /**
     * 拆分字符串
     * @param str 字符串
     * @param regex 拆分的字符
     * @return
     */
    static String[] split(String str, String regex) {
        if(null == str){
            return null;
        }
        return str.split(regex);
    }

    /**
     * 拆分字符串（按“,”拆分）
     * @param str 字符串
     * @return
     */
    static String[] split(String str) {
        if(null == str){
            return null;
        }
        return str.split(StringUtil.COMMA);
    }

    /**
     * 字符串数组拼接
     * @param elements 字符串数组
     * @return
     */
    static String join(Iterable<? extends CharSequence> elements) {
        return String.join(StringUtil.COMMA, elements);
    }

    /**
     * 字符串数组拼接
     * @param elements 字符串数组
     * @return
     */
    static String join(CharSequence... elements) {
        return String.join(StringUtil.COMMA, elements);
    }

    /**
     * 拼接
     * @param values
     * @return
     */
    static String join(Object[] values) {
        return Arrays.stream(values).map(DataUtil::toString)
                .collect(Collectors.joining(StringUtil.COMMA));
    }

    /**
     * 字符串数组是否包含某个字符串
     * @param strings 字符串数组
     * @param sub 包含的字符
     */
    static boolean contains(Iterable<String> strings, String sub) {
        if(null == sub || null == strings ){
            return false;
        }
        for(String s : strings){
            if(sub.equals(s)){
                return true;
            }
        }
        return false;
    }

    /**
     * 字符串数组是否包含某个字符串
     * @param strings 字符串数组
     * @param sub 包含的字符
     * @return
     */
    static boolean contains(String[] strings, String sub){
        return StringUtil.contains(DataUtil.arrayToList(strings), sub);
    }

    /**
     * 字符串是否包含后面的某个子串
     * @param str 字符串
     * @param subs 至少包含其中一个字串
     */
    static boolean contains(String str, Iterable<String> subs) {
        if(null == str || null == subs){
            return false;
        }
        for (String sub : subs) {
            if (str.contains(sub)){
                return true;
            }
        }
        return false;
    }

    /**
     * 字符串是否包含后面的某个子串
     * @param str 字符串
     * @param subs 至少包含其中一个字串
     */
    static boolean contains(String str, String... subs){
        return StringUtil.contains(str, DataUtil.arrayToList(subs));
    }

    /**
     * 交集（两个字符串数组是否存在相同元素）
     * @param strings1 字符串数组1
     * @param strings2 字符串数组2
     */
    static boolean intersection(String[] strings1, String... strings2) {
        if(null == strings1 || null == strings2 || strings1.length == 0 || strings2.length == 0){
            return false;
        }
        for (String s1 : strings1) {
            for (String s2 : strings2) {
                if (s1 == s2 || s1.equals(s2)){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * String集合 转 String[]
     * @param collection String集合
     * @return
     */
    static String[] toArray(Collection<String> collection){
        return null == collection ? null : collection.toArray(new String[]{});
    }

    /**
     * String[] 转 List<String>
     * @param array
     * @return
     */
    static List<String> toList(String... array){
        return DataUtil.arrayToList(array);
    }

    /**
     * 两个字符串是否相等（忽略大小写）
     * @param str1
     * @param str2
     * @return
     */
    static boolean equalsIgnoreCase(String str1, String str2) {
        return str1 != null && str1.equalsIgnoreCase(str2);
    }

    /**
     * 比较两个字符串的大小
     * @param str1
     * @param str2
     * @return
     */
    static int compareTo(String str1, String str2) {
        if (str1 == null) {
            return Integer.MAX_VALUE;
        }
        if (str2 == null) {
            return Integer.MIN_VALUE;
        }
        char[] chars1 = str1.toCharArray();
        char[] chars2 = str2.toCharArray();
        int len = (chars1.length <= chars2.length) ? chars1.length : chars2.length;
        for (int i = 0; i < len; i++) {
            char a = chars1[i];
            char b = chars2[i];
            if(a != b) {
                return a - b;
            }
        }
        return chars1.length - chars2.length;
    }

    /**
     * 比较两个字符串的大小（忽略大小写）
     * @param str1
     * @param str2
     * @return
     */
    static int compareToIgnoreCase(String str1, String str2) {
        if (str1 == null) {
            return Integer.MAX_VALUE;
        }
        if (str2 == null) {
            return Integer.MIN_VALUE;
        }
        char[] chars1 = str1.toCharArray();
        char[] chars2 = str2.toCharArray();
        int len = (chars1.length <= chars2.length) ? chars1.length : chars2.length;
        int diff = chars1.length - chars2.length;
        for (int i = 0; i < len; i++) {
            char a = chars1[i];
            char b = chars2[i];
            if(a != b) {
                a = Character.toLowerCase(a);
                b = Character.toLowerCase(b);
                if(a != b) {
                    return a - b;
                }
                if (diff == 0) {
                    return chars2[i] - chars1[i];
                }
                return diff;
            }
        }
        return diff;
    }

    /**
     * 字符串排序（正序）
     * @param strings
     * @return
     */
    static String[] sort(String ...strings) {
        Arrays.sort(strings, StringUtil::compareToIgnoreCase);
        return strings;
    }

    /**
     * 字符串排序（正序）
     * @param collection
     * @return
     */
    static String[] sort(Collection<String> collection) {
        String[] strings = new String[ collection.size() ];
        collection.toArray(strings);
        Arrays.sort(strings, StringUtil::compareToIgnoreCase);
        return strings;
    }

    /**
     * 字符串排序（倒序）
     * @param strings
     * @return
     */
    static String[] sortDesc(String ...strings) {
        Arrays.sort(strings, (a, b) -> StringUtil.compareToIgnoreCase(b, a));
        return strings;
    }

    /**
     * 字符串排序（倒序）
     * @param collection
     * @return
     */
    static String[] sortDesc(Collection<String> collection) {
        String[] strings = new String[ collection.size() ];
        collection.toArray(strings);
        Arrays.sort(strings, (a, b) -> StringUtil.compareToIgnoreCase(b, a));
        return strings;
    }

    /**
     * 提取字符串中的数字
     * @param str
     * @return
     */
    static String getNumber(String str) {
        return GET_NUMBER_PATTERN.matcher(str).replaceAll(EMPTY);
    }

    /**
     * 处理url参数
     * @param url
     * @param params
     * @return
     */
    static String handlerUrl(String url, Map<String, ?> params) {
        if (CollectionUtils.isEmpty(params)) {
            return url;
        }
        StringBuilder sb = new StringBuilder((url.contains("?") ? '&' : '?'));
        params.forEach((k,v) -> {
            sb.append(k)
                    .append('=')
                    .append(v)
                    .append('&');
        });
        sb.deleteCharAt(sb.length() - 1);
        return url + sb.toString();
    }

    static <T>String toString(T t) {
        if (t == null) {
            return null;
        }
        return t.toString();
    }

    static <T>String toString(Collection<T> ts) {
        if (ts == null) {
            return null;
        }
        return ts.stream().map(StringUtil::toString).collect(Collectors.joining(COMMA));
    }

    static <T>String toString(T[] ts) {
        if (ts == null) {
            return null;
        }
        return Arrays.stream(ts).map(StringUtil::toString).collect(Collectors.joining(COMMA));
    }

    /**
     * 获取匹配内容
     * @param source
     * @param regex
     * @return
     */
    static Set<String> getMatchs(String source, String regex) {
        // "\\$\\{[^}]+\\}"
        Pattern compile = Pattern.compile(regex);
        Set<String> set = new HashSet<>();
        Matcher matcher = compile.matcher(source);
        while (matcher.find()) {
            set.add(matcher.group());
        }
        return set;
    }

    /**
     * 获取匹配内容
     * @param source
     * @param start
     * @param end
     * @return
     */
    static Set<String> getMatchs(String source, String start, String end) {
        return getMatchs(source, start +"[^"+ end +"]+"+ end);
    }

    /**
     * 获取大括号内容
     * @param source
     * @return
     */
    static Set<String> getBraceMatchs(String source) {
        return getMatchs(source, "\\{[^{}]+\\}");
    }

    /**
     * 获取下括号内容
     * @param source
     * @return
     */
    static Set<String> getParenthesesMatchs(String source) {
        return getMatchs(source, "\\([^()]+\\)");
    }

    /**
     * 统计中文数量
     * @param str
     * @return
     */
    static int chineseCount(String str) {
        if (str == null) {
            return 0;
        }
        int count = 0;
        String regEx = "[\u4e00-\u9fa5]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        while(m.find()) {
            count ++;
        }
        return count;
    }

}
